技巧21 不带缓存的重新构建

使用Dockerfile进行构建时会用到一项有用的缓存功能:只有当命令发生更改时才会重建已构建的步骤。代码清单4-5展示了第1章里介绍的todo应用的一次重新构建的输出结果。

代码清单4-5 带缓存的重新构建

$ docker build .
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM node
 ---> 91cbcf796c2c
Step 1 : MAINTAINER ian.miell@gmail.com
 ---> Using cache  ⇽--- 表明此次构建使用了缓存
 ---> 8f5a8a3d9240  ⇽--- 指定缓存的镜像/层ID
Step 2 : RUN git clone -q https://github.com/docker-in-practice/todo.git
 ---> Using cache
 ---> 48db97331aa2
Step 3 : WORKDIR todo
 ---> Using cache
 ---> c5c85db751d6
Step 4 : RUN npm install > /dev/null
 ---> Using cache
 ---> be943c45c55b
Step 5 : EXPOSE 8000
 ---> Using cache
 ---> 805b18d28a65
Step 6 : CMD npm start
 ---> Using cache
 ---> 19525d4ec794
Successfully built 19525d4ec794  ⇽--- 最后镜像是“重新构建”了,但是实际上没有任何变动

这样做的确有用而且省时,但是它往往并不是用户预期的。以前面的Dockerfile为例,假设用户已经修改了源码并且推送到了Git仓库。然而,新的代码并不会被签出,因为 git clone 命令并没有更改。就Docker构建的过程来看,它们是相同的,因此Docker会复用之前缓存的镜像。在这些情况下,用户想要的是在不使用缓存的情况下重新构建镜像。

问题

想要使用Dockerfile进行重新构建时不使用现有缓存。

解决方案

想要在重新构建时强制指定不使用镜像缓存,请在执行 dockerbuild 时带上 –-no-cache 标志。如代码清单4-6所示,使用 --no-cache 运行前面的构建。

代码清单4-6 不使用缓存强制触发一次重新构建

$ docker build --no-cache .   ⇽--- 重新构建Docker镜像时带上--no-cache标志来忽略已缓存的镜像层
Sending build context to Docker daemon  2.56 kB
Sending build context to Docker daemon
Step 0 : FROM node
 ---> 91cbcf796c2c
Step 1 : MAINTAINER ian.miell@gmail.com
 ---> Running in ca243b77f6a1  ⇽--- 此时不再提示有缓存
  ---> 602f1294d7f1  ⇽--- 中间镜像的ID和之前列表里的有所不同
 Removing intermediate container ca243b77f6a1
Step 2 : RUN git clone -q https://github.com/docker-in-practice/todo.git
 ---> Running in f2c0ac021247
 ---> 04ee24faaf18
Removing intermediate container f2c0ac021247
Step 3 : WORKDIR todo
 ---> Running in c2d9cd32c182
 ---> 4e0029de9074
Removing intermediate container c2d9cd32c182
Step 4 : RUN npm install > /dev/null
 ---> Running in 79122dbf9e52
npm WARN package.json todomvc-swarm@0.0.1 No repository field.
 ---> 9b6531f2036a
Removing intermediate container 79122dbf9e52
Step 5 : EXPOSE 8000
 ---> Running in d1d58e1c4b15
 ---> f7c1b9151108
Removing intermediate container d1d58e1c4b15
Step 6 : CMD npm start
 ---> Running in 697713ebb185
 ---> 74f9ad384859
Removing intermediate container 697713ebb185
Successfully built 74f9ad384859  ⇽--- 一个新的镜像构建出来了

输出内容显示没有提到缓存,而且每个中间层的ID和代码清单4-5里的输出也有所不同。

在其他情况下也有可能遇到类似的问题。我们在早期使用Dockerfile的时候就遇到了一些坑,当网络抖动时一条命令可能无法从网络上正确地检索到某些东西,但是它不会报错。我们持续调用 dockerbuild ,但是生成的bug不会消失!这是因为“坏”镜像已经放进了缓存,而我们当时并不了解Docker缓存的工作方式。最终我们搞明白了。

讨论

一旦完成最终版本的Dockerfile,删除缓存可能是一个有用的健全性检查,这样可以确保它自顶向下是工作的,特别是当用户在公司里使用内部的Web资源而同时又在迭代Dockerfile的过程中可能做了一些改动的时候。如果用户正在使用的是 ADD ,那么不会出现这样的情况,因为Docker会在每次下载文件时检查是否有做过改动,但是当用户相当肯定它会保持不变并且只想继续编写Dockerfile的其他部分时,这样的做法可能会很烦人。

results matching ""

    No results matching ""